from fastapi import HTTPException
from sqlalchemy.ext.asyncio import AsyncSession

from module_admin.entity.vo.common_vo import CrudResponseModel
from module_kylin.dao.future_strategy_position_dao import FutureStrategyPositionDao
from module_kylin.entity.vo.future_strategy_position_vo import (
    FutureStrategyPositionModel,
    FutureStrategyPositionPageQueryModel,
    DeleteFutureStrategyPositionModel,
)


class FutureStrategyPositionService:
    """
    期货策略仓位服务层
    """

    @classmethod
    async def get_strategy_position_list(cls, db: AsyncSession, query_model: FutureStrategyPositionPageQueryModel,
                                         is_page: bool = False):
        """
        获取策略仓位列表

        :param db: 数据库会话
        :param query_model: 查询参数
        :param is_page: 是否开启分页
        :return: 策略仓位列表
        """
        try:
            # 获取策略仓位列表
            strategy_position_page = await FutureStrategyPositionDao.get_strategy_position_list(db, query_model,
                                                                                                is_page)

            return strategy_position_page
        except Exception as e:
            raise HTTPException(status_code=500, detail=str(e))

    @classmethod
    async def get_strategy_position_detail(cls, db: AsyncSession, position_id: int):
        """
        获取策略仓位详情

        :param db: 数据库会话
        :param position_id: 仓位id
        :return: 策略仓位详情
        """
        try:
            # 获取策略仓位详情
            strategy_position_detail = await FutureStrategyPositionDao.get_strategy_position_by_id(db, position_id)

            if not strategy_position_detail:
                raise HTTPException(status_code=404, detail=f"策略仓位{position_id}不存在")

            return strategy_position_detail
        except HTTPException as e:
            raise e
        except Exception as e:
            raise HTTPException(status_code=500, detail=str(e))

    @classmethod
    async def add_strategy_position(cls, db: AsyncSession, position: FutureStrategyPositionModel):
        """
        添加策略仓位

        :param db: 数据库会话
        :param position: 策略仓位信息
        :return: 操作结果
        """
        try:
            # 检查必填字段
            if not position.date or not position.strategy_instance:
                raise HTTPException(status_code=400, detail="日期和策略实例名称不能为空")

            # 检查策略仓位是否已存在
            existing_position = await FutureStrategyPositionDao.get_strategy_position_by_info(db, position)
            if existing_position:
                raise HTTPException(status_code=400, detail=f"该日期的{position.strategy_instance}策略仓位已存在")

            # 添加策略仓位
            new_position = await FutureStrategyPositionDao.add_strategy_position(db, position)
            await db.commit()

            return new_position
        except HTTPException as e:
            await db.rollback()
            raise e
        except Exception as e:
            await db.rollback()
            raise HTTPException(status_code=500, detail=str(e))

    @classmethod
    async def update_strategy_position(cls, db: AsyncSession, position_id: int, position: FutureStrategyPositionModel):
        """
        更新策略仓位

        :param db: 数据库会话
        :param position_id: 仓位id
        :param position: 策略仓位信息
        :return: 操作结果
        """
        try:
            # 检查策略仓位是否存在
            existing_position = await FutureStrategyPositionDao.get_strategy_position_by_id(db, position_id)
            if not existing_position:
                raise HTTPException(status_code=404, detail=f"策略仓位{position_id}不存在")

            # 如果更新了日期和策略实例名称，检查是否与其他记录冲突
            if position.date and position.strategy_instance and (
                    position.date != existing_position.date or position.strategy_instance != existing_position.strategy_instance):
                check_position = FutureStrategyPositionModel(
                    date=position.date,
                    strategy_instance=position.strategy_instance
                )
                conflict_position = await FutureStrategyPositionDao.get_strategy_position_by_info(db, check_position)
                if conflict_position and conflict_position.id != position_id:
                    raise HTTPException(status_code=400, detail=f"该日期的{position.strategy_instance}策略仓位已存在")

            # 更新策略仓位
            await FutureStrategyPositionDao.update_strategy_position(db, position_id, position)
            await db.commit()

            return existing_position
        except HTTPException as e:
            await db.rollback()
            raise e
        except Exception as e:
            await db.rollback()
            raise HTTPException(status_code=500, detail=str(e))

    @classmethod
    async def delete_strategy_position(cls, db: AsyncSession, delete_model: DeleteFutureStrategyPositionModel):
        """
        删除策略仓位

        :param db: 数据库会话
        :param delete_model: 删除参数
        :return: 操作结果
        """
        try:
            # 检查策略仓位是否存在
            for position_id in delete_model.ids:
                existing_position = await FutureStrategyPositionDao.get_strategy_position_by_id(db, position_id)
                if not existing_position:
                    raise HTTPException(status_code=404, detail=f"策略仓位{position_id}不存在")

            # 批量删除策略仓位
            await FutureStrategyPositionDao.batch_delete_strategy_position(db, delete_model.ids)
            await db.commit()

            return CrudResponseModel(is_success=True, message='删除成功')
        except HTTPException as e:
            await db.rollback()
            raise e
        except Exception as e:
            await db.rollback()
            raise HTTPException(status_code=500, detail=str(e))
